home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
SNNSV32.ZIP
/
SNNSv3.2
/
kernel
/
sources
/
kr_inversion.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-04-25
|
8KB
|
277 lines
/**********************************************************************
FILE : @(#)kr_inversion.c 1.11
SHORTNAME :
SNNS VERSION : 3.2
PURPOSE : Implement Kindermann/Linden-inversion-method
NOTES : The functions implemented here closely resemble the
the functions propagateNetForward and propagateNetBackward2
in the file learn_f.c.
FUNCTIONS : -- kr_initInversion
Purpose : initialize net for inversion algorithm
Calls : int kr_topoCheck();
int kr_IOCheck();
int kr_topoSort();
-- kr_inv_forwardPass
Purpose : topological forward propagation
Calls : nothing
-- kr_inv_backwardPass
Purpose : Backward error propagation (topological)
Calls : nothing
AUTHOR : Guenter Mamier
DATE : 04.02.92
CHANGED BY : Sven Doering, Michael Vogt
IDENTIFICATION : @(#)kr_inversion.c 1.11 3/15/94
SCCS VERSION : 1.11
LAST CHANGE : 3/15/94
Copyright (c) 1990-1994 SNNS Group, IPVR, Univ. Stuttgart, FRG
**********************************************************************/
#include <stdio.h>
#include <math.h>
#include <values.h>
#include "kr_typ.h"
#include "kr_const.h"
#include "kernel.h"
#include "kr_def.h"
#include "kr_mac.h"
#include "kr_inversion.ph"
/*****************************************************************************
FUNCTION : kr_initInversion
PURPOSE : initialize net for inversion algorithm
NOTES :
UPDATE : 06.02.92
******************************************************************************/
int kr_initInversion(void)
{
int ret_code = KRERR_NO_ERROR;
if (NetModified || (TopoSortID != TOPOLOGICAL_FF &&
TopoSortID != TOPOLOGIC_LOGICAL)){
/* Net has been modified or topologic array isn't initialized */
/* check the topology of the network */
ret_code = kr_topoCheck();
if (ret_code < KRERR_NO_ERROR)
return( ret_code ); /* an error has occured */
if (ret_code < 2)
return( KRERR_NET_DEPTH ); /* the network has less then 2 layers */
/* count the no. of I/O units and check the patterns */
ret_code = kr_IOCheck();
if(ret_code < KRERR_NO_ERROR)
return( ret_code );
/* sort units by topology and by topologic type */
ret_code = kr_topoSort( TOPOLOGICAL_FF );
}
return(ret_code);
}
/*****************************************************************************
FUNCTION : kr_inv_forwardPass
PURPOSE : topological forward propagation
NOTES :
UPDATE : 29.01.92
******************************************************************************/
void kr_inv_forwardPass(struct UnitList *inputs)
{
register struct Unit *unit_ptr;
register TopoPtrArray topo_ptr; /* points to a topological sorted */
/* unit stucture (input units first) */
struct UnitList *IUnit; /* working list of input units */
/* initialize the topological pointer */
topo_ptr = topo_ptr_array;
/* calculate the activation and output value of the input units */
IUnit = inputs;
while((unit_ptr = *++topo_ptr) != NULL){
/* clear error values */
unit_ptr->Aux.flint_no = 0.0;
if(unit_ptr->out_func == OUT_IDENTITY)
unit_ptr->Out.output = unit_ptr->act = IUnit->act;
else /* no identity output function: calculate unit's output also */
unit_ptr->Out.output = (*unit_ptr->out_func)(unit_ptr->act = IUnit->act);
IUnit = IUnit->next;
}
/* popagate hidden units */
while((unit_ptr = *++topo_ptr) != NULL){
/* clear error values */
unit_ptr->Aux.flint_no = 0.0;
/* calculate the activation value of the unit:
call the activation function if needed */
unit_ptr->act = (*unit_ptr->act_func) (unit_ptr);
if(unit_ptr->out_func == OUT_IDENTITY)
unit_ptr->Out.output = unit_ptr->act;
else
/* no identity output function: calculate unit's output also */
unit_ptr->Out.output = (*unit_ptr->out_func) (unit_ptr->act);
}
/* popagate output units */
while((unit_ptr = *++topo_ptr) != NULL){
/* clear error values */
unit_ptr->Aux.flint_no = 0.0;
/* calculate the activation value of the unit:
call the activation function if needed */
unit_ptr->act = (*unit_ptr->act_func) (unit_ptr);
if(unit_ptr->out_func == OUT_IDENTITY)
unit_ptr->Out.output = unit_ptr->act;
else /* no identity output function: calculate unit's output also */
unit_ptr->Out.output = (*unit_ptr->out_func) (unit_ptr->act);
}
}
/*****************************************************************************
FUNCTION : kr_inv_backwardPass
PURPOSE : Backward error propagation (topological)
NOTES :
UPDATE : 04.02.92
*****************************************************************************/
double kr_inv_backwardPass(float learn, float delta_max, int *err_units,
float ratio, struct UnitList *inputs,
struct UnitList *outputs)
{
register struct Link *link_ptr;
register struct Site *site_ptr;
register struct Unit *unit_ptr;
register float error, sum_error, eta, devit;
register TopoPtrArray topo_ptr;
struct UnitList *IUnit, *OUnit;
sum_error = 0.0; /* reset network error */
*err_units = 0; /* reset error units */
eta = learn; /* store learn_parameter in CPU register */
/* add 3 to no_of_topo_units because topologic array contains 4 NULL
pointers */
topo_ptr = topo_ptr_array + (no_of_topo_units + 3);
/* calculate output units only */
OUnit = outputs;
while(OUnit->next != NULL)OUnit = OUnit->next;
while((unit_ptr = *--topo_ptr) != NULL){
/* calc. devitation */
devit = OUnit->i_act - unit_ptr->Out.output;
OUnit->act = unit_ptr->Out.output;
OUnit = OUnit->prev;
if ( (devit > -delta_max) && (devit < delta_max) ){
continue;
}else{
*err_units += 1;
}
/* sum up the error of the network */
sum_error += devit * devit;
/* calc. error for output units */
error = devit * (unit_ptr->act_deriv_func) ( unit_ptr );
/* error = devit;*/
/* Calculate sum of errors of predecessor units */
if(UNIT_HAS_DIRECT_INPUTS( unit_ptr )){
FOR_ALL_LINKS( unit_ptr, link_ptr )
link_ptr->to->Aux.flint_no += link_ptr->weight * error;
}else{ /* the unit has sites */
FOR_ALL_SITES_AND_LINKS( unit_ptr, site_ptr, link_ptr )
link_ptr->to->Aux.flint_no += link_ptr->weight * error;
}
}
/* calculate hidden units only */
while((unit_ptr = *--topo_ptr) != NULL){
/* calc. the error of the (hidden) unit */
error = (unit_ptr->act_deriv_func) ( unit_ptr ) * unit_ptr->Aux.flint_no;
error = unit_ptr->Aux.flint_no;
/* Calculate sum of errors of predecessor units */
if(UNIT_HAS_DIRECT_INPUTS( unit_ptr )){
FOR_ALL_LINKS( unit_ptr, link_ptr )
link_ptr->to->Aux.flint_no += link_ptr->weight * error;
}else{ /* the unit has sites */
FOR_ALL_SITES_AND_LINKS( unit_ptr, site_ptr, link_ptr )
link_ptr->to->Aux.flint_no += link_ptr->weight * error;
}
unit_ptr->act = unit_ptr->i_act;
}
/* calculate input units only */
IUnit = inputs;
while(IUnit->next != NULL)IUnit = IUnit->next;
while((unit_ptr = *--topo_ptr) != NULL){
/* calc. the error of the (input) unit */
error = (unit_ptr->act_deriv_func) ( unit_ptr ) * unit_ptr->Aux.flint_no;
error = unit_ptr->Aux.flint_no;
/* Calculate the new activation for the input units */
IUnit->im_act += eta * error + ratio*(IUnit->i_act - (float)unit_ptr->act);
unit_ptr->act = 1.0 / (1.0 + exp((double)(-IUnit->im_act)));
IUnit->act = unit_ptr->act;
IUnit = IUnit->prev;
}
/* return the error of the network */
sum_error *= 0.5;
return( sum_error );
}